﻿<style>

.resultTable .el-table__header-wrapper {
  display: none;
}

.resultTableHeader .el-table__body-wrapper {
  padding-bottom: 20px;
}

.resultTable .el-button {
  padding: 0 !important;
}

.excel-view-tab.el-tabs--border-card > .el-tabs__content {
  padding: 5px;
}

.excel-view-tab .el-tabs__item {
  height: 30px;
  line-height: 30px;
}

.excel-view-tab .el-tabs__nav-next, .excel-view-tab .el-tabs__nav-prev {
  line-height: 30px;
}

#data-tab .el-tabs__header.is-top {
  margin: 0;
}

.excel-view .el-table td, .excel-view .el-table th {
  padding: 2px 0;
  height: 28px;
}

.excel-view .el-table th, .el-table tr.changed {
  background-color: #fdf6ec;
}

.excel-view .el-table td.is-hidden > * {
  visibility: visible;
}

.excel-view .el-input__inner {
  padding: 0 8px;
  height: auto;
  border: none;
  background: none;
  line-height: normal;
}

/*.excel-view .el-table .cell-selected {*/
/*  background-color: #9ed0ff!important;*/
/*}*/
</style>
<style scoped>
/** excelview   border 增加颜色 */
/*>>> .el-table--border:after,.el-table--group:after,.el-table:before {*/
/*  background-color: #C0C0C0;*/
/*}*/
/*>>> .el-table--border,.el-table--group {*/
/*  border-color: #C0C0C0;*/
/*}*/
/*>>> .el-table td,.el-table th.is-leaf {*/
/*  border-bottom: 1px solid #C0C0C0;*/
/*}*/
/*>>> .el-table--border th,.el-table--border th.gutter:last-of-type {*/
/*  border-bottom: 1px solid #C0C0C0;*/
/*}*/
/*>>> .el-table--border td,.el-table--border th {*/
/*  border-right: 1px solid #C0C0C0;*/
/*}*/

</style>
<template>

  <el-tabs v-if="excelData.sheetList&&excelData.sheetList.length>0" type="border-card" class="excel-view-tab" @tab-click="changeResultTab(resultTabName)" v-model="resultTabName">
    <el-tab-pane v-for="sheet in excelData.sheetList" :key="sheet.name" :label="sheet.name"
                 :lazy="true" :name="sheet.name">
      <span v-if="sheet.icon" slot="label"><i :class="sheet.icon"></i> {{sheet.name}}</span>
      <div class="excel-view" style="padding-bottom: 2px;">
        <el-row :style="'height:'+displayMap[sheet.name].frozenTableHeight+'px;'+'overflow:hidden'"
                :ref="'resulttable_frozen_div_'+sheet.name">
          <el-table v-if="excelData.sheetFrozenDataListMap&&excelData.sheetFrozenDataListMap[sheet.name]"
                    :id="'resulttable_frozen_'+(sheet.id?sheet.id:sheet.name)" :ref="'resulttable_frozen_'+sheet.name" border
                    :data="excelData.sheetFrozenDataListMap[sheet.name]"
                    class="resultTableHeader"
                    :show-header="false"
                    @mouseout.native="handleMouseOut"
                    @mousemove.native="handleMouseMove"
                    @cell-mouse-enter="(row, column, cell, event)=>handleMouseEnter(row, column, cell, event)"
                    @mousedown.native="($event) => handleMouseDown($event, 'resulttable_frozen_'+sheet.name,'resulttable_data_'+sheet.name)"
                    :span-method="(val) => {return excelMergeMethod(val,sheet)}"
                    :cell-style="(val) => {return headerExcelCellStyle(val,sheet,cellStyle)}"
                    @cell-click="(row, column, cell,event)=>cellClick(row,column,cell,event,sheet)"
                    :style="tableStyle"
                    :key="'output_frozen_'+sheet.name+viewVersion">
            <el-table-column v-for="(col,index) in sheet.colIdList"
                             :key="col"
                             :prop="col"
                             :fixed="index<sheet.frozenCol"
                             show-overflow-tooltip
                             :width="columnWidthMap[sheet.name+'$'+col]"
                             align="center" >
              <template slot-scope="scope">
                <template v-if="scope.row[col]&&(scope.row[col]+'').startsWith('data:image')">
                  <img :src="scope.row[col]">
                </template>
                <template v-else>
                  <template v-if="editCellIndex==(sheet.name+'_'+scope.row['virtualRowNum']+'_'+col)">
                    <el-input :key="'cellInput_'+editCellIndex" :ref="'cellInput_'+editCellIndex" @blur="cancelEdit" @input="()=>{changeInput(scope.row)}" type="text" v-model="scope.row[col]"></el-input>
                  </template>
                  <span v-else-if="scope.row[col]&&scope.row[col+'_fixed']">
                    <template v-if="detailCellIndex==(sheet.name+'_'+scope.row['virtualRowNum']+'_'+col)">
                      {{scope.row[col]}}
                    </template>
                    <template v-else>
                      {{isNaN(scope.row[col])?(formatText?formatText(scope,sheet):scope.row[col]):Number(scope.row[col]).toFixed(Number(scope.row[col+'_fixed']))}}
                    </template>
                    </span>
                  <span  v-else-if="scope.row[col]&&scope.row[col].indexOf('\n')>=0" style="visibility: visible;" v-html="scope.row[col].replace(/\n/g,'<br>')">
                </span>
                  <span v-else>
                    {{scope.row[col]?(formatText?formatText(scope,sheet):(scope.row[col]+'').replace(/ /g,'&nbsp;')):''}}
                  </span>
                </template>
              </template>
            </el-table-column>

            <el-table-column show-overflow-tooltip v-for="item in rightFixColumns.filter(fixCol=>rightFixColumnShowable(fixCol,sheet))" fixed="right" :width="item.width">
              <template slot-scope="scope">
                {{item.label}}
              </template>
            </el-table-column>

            <el-table-column v-if="displayMap[sheet.name].scrollBarWidth>0"
                             :fixed="rightFixColumns&&rightFixColumns.length>0?'right':false"
                             :width="displayMap[sheet.name].scrollBarWidth"></el-table-column>
          </el-table>
        </el-row>
        <el-table
            v-if="displayMap[sheet.name].bodyTableHeight&&displayMap[sheet.name].bodyTableHeight>0"
            :id="'resulttable_data_'+(sheet.id?sheet.id:sheet.name)" :ref="'resulttable_data_'+sheet.name" border
                  :data="sheet.bodyDataList"
                  :virtual="virtualModeMap[sheet.name]"
                  @virtual-change="updateVirtualDataRange($event)"
                  :show-header="false"
                  :itemHeight="28"
                  class="resultTable" :max-height="displayMap[sheet.name].bodyTableHeight"
                  @cell-dblclick="(row, column, cell)=>showCellDetail(sheet,row,column)"
                  @cell-click="(row, column, cell,event)=>cellClick(row,column,cell,event,sheet)"
                  @row-click="rowClick"
                  :row-class-name="rowClassName"
                  :span-method="(val) => {return excelMergeMethod(val,sheet,sheet.frozenRow)}"
                  :cell-style="(val) => {return bodyExcelCellStyle(val,sheet,cellStyle)}"
                  @mouseout.native="handleMouseOut"
                  @mousemove.native="handleMouseMove"
                  @cell-mouse-enter="(row, column, cell, event)=>handleMouseEnter(row, column, cell, event)"
                  @mousedown.native="($event) => handleMouseDown($event, 'resulttable_data_'+sheet.name, 'resulttable_frozen_'+sheet.name)"
                  :style="tableStyle"
                  :key="'output_data_'+sheet.name+viewVersion">
          <el-table-column v-for="(col,index) in sheet.colIdList"
                           :key="col"
                           :prop="col"
                           :fixed="index<sheet.frozenCol"
                            show-overflow-tooltip
                           :width="columnWidthMap[sheet.name+'$'+col]"
                           :align="sheet.colAlignMap&&sheet.colAlignMap[col]?sheet.colAlignMap[col]:'center'">
            <template slot-scope="scope">
              <template v-if="scope.row[col]&&(scope.row[col]+'').startsWith('data:image')">
                <img :src="scope.row[col]">
              </template>
              <template v-else>
                <template v-if="editCellIndex==(sheet.name+'_'+scope.row['virtualRowNum']+'_'+col)">
                  <el-input :key="'cellInput_'+editCellIndex" :ref="'cellInput_'+editCellIndex" @blur="cancelEdit(scope.row,scope.column)" @input="()=>{changeInput(scope.row,scope.column)}" type="text" v-model="scope.row[col]"></el-input>
                </template>
                <span v-else-if="scope.row[col]&&scope.row[col+'_fixed']">
                    <template v-if="detailCellIndex==(sheet.name+'_'+scope.row['virtualRowNum']+'_'+col)">
                      {{scope.row[col]}}
                    </template>
                    <template v-else>
                      {{isNaN(scope.row[col])?(formatText?formatText(scope,sheet):scope.row[col]):Number(scope.row[col]).toFixed(Number(scope.row[col+'_fixed']))}}
                    </template>
                    </span>
                <span v-else>
                    {{scope.row[col]?(formatText?formatText(scope,sheet):(scope.row[col]+'').replace(/ /g,'&nbsp;')):''}}
                  </span>
              </template>
            </template>
          </el-table-column>

          <el-table-column show-overflow-tooltip v-for="item in rightFixColumns.filter(fixCol=>rightFixColumnShowable(fixCol,sheet))" :key="item.id+'-fixed'" fixed="right" :width="item.width">
            <template v-if="scope.row[item.id]" slot-scope="scope">
              <el-button v-if="item.type=='button'" type="text" @click="item.click(scope.row)">{{scope.row[item.id]}}
              </el-button>
              <span v-else>{{scope.row[item.id]}}</span>
            </template>
          </el-table-column>
        </el-table>
      </div>

    </el-tab-pane>
  </el-tabs>
  <el-empty v-else description="无标签页数据">
  </el-empty>
</template>

<script>

import {addClass, hasClass, removeClass} from "element-ui/src/utils/dom";

window.getScrollBarWidth = function() {

  if (window.scrollBarWidth !== undefined) return window.scrollBarWidth;

  const outer = document.createElement('div');
  outer.className = 'el-scrollbar__wrap';
  outer.style.visibility = 'hidden';
  outer.style.width = '100px';
  outer.style.position = 'absolute';
  outer.style.top = '-9999px';
  document.body.appendChild(outer);

  const widthNoScroll = outer.offsetWidth;
  outer.style.overflow = 'scroll';

  const inner = document.createElement('div');
  inner.style.width = '100%';
  outer.appendChild(inner);

  const widthWithScroll = inner.offsetWidth;
  outer.parentNode.removeChild(outer);
  let scrollBarWidth = widthNoScroll - widthWithScroll;

  window.scrollBarWidth = scrollBarWidth;
  return scrollBarWidth;
};
export default {
  name: "ExcelView",
  props: {
    data: {},
    maxHeight: {type: Number, default: 0},
    cellStyle: {
      type: Function,
      default: () => {
      }
    },
    formatText: {
      type: Function,
      default: null
    },
    cellEditable: {
      type: Function,
      default: null
    },
    minTextLength: {
      type: Number,
      default: 1
    },
    maxTextLength: {
      type: Number,
      default: -1
    },
    rightFixColumns: {
      type: Array,
      default: []
    },
    //背景色
    backgroundColor:{
      type:String,
      default:''
    },
    //边框颜色
    borderColor:{
      type:String,
      default:''
    },
    //行选中颜色
    rowSelectedColor:{
      type:String,
      default:'lightgreen'
    },
    //单元格正在编辑颜色
    cellEditingColor:{
      type:String,
      default:'#5584ff82'
    },
    //单元格可编辑颜色
    cellEditableColor:{
      type:String,
      default:'limegreen'
    },
    //行数据已编辑颜色
    rowEditedColor:{
      type:String,
      default:'#fdf6ec'
    }
  },
  watch: {
    data() {
      // this.excelData = this.data;
      this.viewVersion++;
      this.init();
    },
    maxHeight(){
      this.updateBodyHeight(this.resultTabName);
    },

  },
  data() {
    return {
      excelData: {},
      isLoading: true,
      loadingText: '正在处理...',
      resultTabName: '',
      currentScrollUpdateTask: null,
      detailCellIndex: '',
      editCellIndex:'',
      columnWidthMap: {},
      // bodyVerticalScroll:false,
      updateIndex: 0,//用于通知重新计算表格高度
      virtualModeMap: {},
      virtualDataRangeMap:{},
      displayMap:{},
      viewVersion:1,
      draggingColumn:null,//当前拖拽列
      dragging:false,//正在拖拽
      selectedRowMap: {},//选中行
      tableStyle:{},
    }
  },
  computed: {
  },
  created: function () {
  },
  mounted: function () {
    this.init();
  },

  methods: {
    //初始化数据
    init() {
      this.excelData = this.data;
      if(this.borderColor) {
        this.tableStyle['border-color'] = this.borderColor;
      }
      if(!this.excelData.sheetList||this.excelData.sheetList.length<1) {
        return;
      }
      if (!this.resultTabName) {
        this.resultTabName = this.excelData.sheetList[0].name;
      } else {
        let currentSheetName = this.excelData.sheetList[0].name;
        for (let item of this.excelData.sheetList) {
          if (this.resultTabName == item.name) {
            currentSheetName = this.resultTabName;
            break;
          }
        }
        this.resultTabName = currentSheetName;
      }
      let mergeRange = {};
      let displayMap = {};
      this.excelData.sheetFrozenDataListMap = {};
      for (let sheet of this.excelData.sheetList) {
        let sheetName = sheet.name;

        displayMap[sheetName] = {frozenTableHeight:0,bodyTableHeight:0,scrollBarWidth:17};

        if (!sheet.cellMergeList) {
          sheet.cellMergeList = [];
        }
        //此处加一个合并区域，用来处理表头右侧填充滚动条空缺
        sheet.cellMergeList.push({
          firstRow: 0,
          lastRow: sheet.frozenRow - 1,
          firstColumn: sheet.colIdList.length,
          lastColumn: sheet.colIdList.length
        })
        //记录单元格是否在合并区域内
        let mergeCellMap = {};

        //右侧固定列特殊处理，合并表头
        if (this.rightFixColumns && this.rightFixColumns.length > 0 && sheet.frozenRow > 0) {
          for (let i = 0; i < this.rightFixColumns.length; i++) {
            sheet.cellMergeList.push({
              firstRow: 0,
              lastRow: sheet.frozenRow - 1,
              firstColumn: sheet.colIdList.length + i,
              lastColumn: sheet.colIdList.length + i
            });
          }

        }
        //最后一列为占位符，宽度等于下方滚动条宽度
        let offset = this.rightFixColumns ? this.rightFixColumns.length : 0;
        sheet.cellMergeList.push({
          firstRow: 0,
          lastRow: sheet.frozenRow - 1,
          firstColumn: sheet.colIdList.length + offset,
          lastColumn: sheet.colIdList.length + offset
        });
        for (let item of sheet.cellMergeList) {
          for (let i = item.firstRow; i <= item.lastRow; i++) {
            let rowspan = 0;
            if (i == item.firstRow) {
              rowspan = item.lastRow - item.firstRow + 1;
            }
            let horizontalMerge = item.lastColumn - item.firstColumn > 0;
            for (let j = item.firstColumn; j <= item.lastColumn; j++) {
              if (horizontalMerge) {
                mergeCellMap[i + ',col' + j] = true;
              }
              let colspan = 0;
              if (j == item.firstColumn) {
                colspan = item.lastColumn - item.firstColumn + 1;
              }
              mergeRange[sheetName + "_" + i + '_' + j] = {
                rowspan: rowspan,
                colspan: colspan,
                align: item.align
              };
            }
          }
        }

        for (let col of sheet.colIdList) {
          let widthResult = this.judgeAvgColumnWidth(sheet, col, sheet.dataList, mergeCellMap)
          this.columnWidthMap[sheet.name + '$' + col] = widthResult;
        }
        let dataList = [];
        if (sheet.frozenRow >= sheet.dataList.length) {
          sheet.frozenRow = 0;
        }
        for (let i = 0; i < sheet.frozenRow; i++) {
          dataList.push(sheet.dataList[i]);
        }
        //将主数据去除锁定行数据
        let bodyDataList = [];
        for (let i = 0; i < sheet.dataList.length; i++) {
          let rowData = sheet.dataList[i];
          rowData.rowNum = i;
          if (i < sheet.frozenRow) {
            continue;
          }
          bodyDataList.push(rowData);
          rowData.virtualRowNum = i - sheet.frozenRow;
          for (let item of this.rightFixColumns) {
            if (!item.id || !item.formatter) {
              continue;
            }
            rowData[item.id] = item.formatter(rowData);
          }
        }
        sheet.bodyDataList = bodyDataList;
        if(sheet.dataList.length*28>this.maxHeight*2&&sheet.dataList.length>30) {
          //如果数据过多，则开启该标签页虚拟视图
          //虚拟视图下存在问题，临时关闭虚拟视图模式
          // this.virtualModeMap[sheet.name] = true;
        }
        this.excelData.sheetFrozenDataListMap[sheetName] = dataList;
      }
      this.excelData.mergeRangeMap = mergeRange;

      this.displayMap = displayMap;
      this.changeResultTab(this.resultTabName);
      this.updateIndex++;
    },
    rowClick(row, column, event) {
      this.$emit('row-click', row)
    },
    cellClick(row, column, cell, event, sheet) {
      this.selectedRowMap[sheet.name] = row.rowNum;
      //重新生成map，否则无法及时监听
      this.selectedRowMap = JSON.parse(JSON.stringify(this.selectedRowMap));
      this.$emit('cell-click', row, column, cell, event, sheet)
      let canEdit = false;
      if(this.cellEditable) {
        canEdit = this.cellEditable(row, column, sheet);
      }
      if(!canEdit) {
        return;
      }
      this.editCell(sheet,row,column)
    },

    syncResultHeader2DataTableScroll: function () {

      const headerDom = this.$refs['resulttable_frozen_' + this.resultTabName][0].bodyWrapper
      const dataDom = this.$refs['resulttable_data_' + this.resultTabName][0].bodyWrapper;
      let scrollLeft = headerDom.scrollLeft
      if (dataDom.scrollLeft != scrollLeft) {
        dataDom.scrollLeft = scrollLeft;

      }

    },
    syncResultData2HeaderTableScroll: function () {

      const headerDom = this.$refs['resulttable_frozen_' + this.resultTabName][0].bodyWrapper
      const dataDom = this.$refs['resulttable_data_' + this.resultTabName][0].bodyWrapper;
      let scrollLeft = dataDom.scrollLeft
      if (headerDom.scrollLeft != scrollLeft) {
        headerDom.scrollLeft = scrollLeft;

      }

    },
    //切换结果标签页事件
    changeResultTab: function (tab) {
      this.excelData.currentSheet = tab;
      // if (this.currentScrollUpdateTask != null) {
      //   clearTimeout(this.currentScrollUpdateTask);
      // }
      let displayData = this.displayMap[tab];
      this.$nextTick(() => {
        if (!this.excelData.sheetFrozenDataListMap
            || !this.excelData.sheetFrozenDataListMap[tab]
            || this.excelData.sheetFrozenDataListMap[tab].length < 1) {
          displayData.frozenTableHeight = 0;
        } else {
          displayData.frozenTableHeight = this.$refs['resulttable_frozen_' + tab][0].bodyWrapper.children[0].offsetHeight;
        }

        // this.currentScrollUpdateTask = null;
        this.updateBodyHeight(tab);
      });
    },
    updateBodyHeight(tab){
      let displayData = this.displayMap[tab];
      let bodyHeight = this.maxHeight - displayData.frozenTableHeight - 42 > 90 ? this.maxHeight - displayData.frozenTableHeight - 42 : displayData.frozenTableHeight + 200 - 42;
      displayData.bodyTableHeight = bodyHeight;
      this.$nextTick(() => {
        const dataTableRef = this.$refs['resulttable_data_' + tab];
        const headerDom = this.$refs['resulttable_frozen_' + tab][0].bodyWrapper;
        const dataDom = dataTableRef[0].bodyWrapper;

        headerDom.removeEventListener('scroll', this.syncResultHeader2DataTableScroll);
        dataDom.removeEventListener('scroll', this.syncResultData2HeaderTableScroll);
        headerDom.addEventListener('scroll', this.syncResultHeader2DataTableScroll);
        dataDom.addEventListener('scroll', this.syncResultData2HeaderTableScroll);

        if (dataTableRef && dataTableRef.length > 0) {
          let bodyVerticalScroll = dataDom.scrollHeight > bodyHeight;
          if (bodyVerticalScroll) {
            displayData.scrollBarWidth = window.getScrollBarWidth();
          } else {
            displayData.scrollBarWidth = 0;
          }
        }
      });
    },
    /**
     * 计算列宽
     * @param text
     * @returns {number}
     */
    judgeColumnWidth: function (text) {
      return (text.length + 1) * 14;
    },
    /**
     * 查找某列合理的最长字符串
     * @param text
     * @returns {number}
     */
    judgeLongestColumnWidth: function (col, dataList) {
      let text = '默认字';
      let text2 = '默认字';
      if (col == undefined || dataList == undefined) {
        return this.judgeColumnWidth(text);
      }
      for (let item of dataList) {
        let data = item[col];
        if (data && (data+'').startsWith('data:image')) {
          continue;
        }
        if (data != undefined && data.length > text.length) {
          text = data;
        } else if (data != undefined && data.length > text2.length) {
          text2 = data;
        }
      }

      if (text.length > text2.length * 1.5) {
        //如果排名第一的字符串长度超过第二的字符串长度1.5倍，则认为不合理
        text = text2;
      }
      return this.judgeColumnWidth(text);
    },
    /**
     * 查找某列合理的最长字符串
     * @param text
     * @returns {number}
     */
    judgeAvgColumnWidth: function (sheet, col, dataList, mergeCellMap) {
      if (col == undefined || dataList == undefined) {
        return 0;
      }
      let wordSum = 0;
      let count = 0;
      let maxLength = 3;
      // for(let item of dataList) {
      for (let i = 0; i < dataList.length; i++) {
        let item = dataList[i];
        let data = item[col];
        if (data && (data+'').startsWith('data:image')) {
          //图片展示特殊处理
          const image = new Image();
          image.src = data;
          image.onload = ()=>{
            if(!image.width) {
              return;
            }
            if(this.columnWidthMap[sheet.name+'$'+col]&&this.columnWidthMap[sheet.name+'$'+col]>image.width) {
              return;
            }
            this.columnWidthMap[sheet.name+'$'+col] = image.width;
          };
          continue;
        }
        if (mergeCellMap && mergeCellMap[i + ',' + col]) {
          //如果是合并区域内单元格，则忽略
          continue;
        }

        if (data && (data+'').startsWith('data:image')) {
          const image = new Image();
          image.src = data;
          image.onload = ()=>{
            if(!image.width) {
              return;
            }
            if(this.columnWidthMap[sheet.name+'$'+col]&&this.columnWidthMap[sheet.name+'$'+col]>image.width) {
              return;
            }
            this.columnWidthMap[sheet.name+'$'+col] = image.width;
          };
          continue;
        }
        if (data && data.length > 0) {
          count++;
          // 统计其他字符
          let minusLength = 0;
          let charArray = data.match(/[0-9a-zA-Z]/g);
          if(charArray) {
            minusLength = charArray.length/2;
          }
          charArray = data.match(/[ \.]/g);
          if(charArray) {
            //.、空格只占四分之一宽度
            minusLength += charArray.length/4*2.8;
          }
          let wordLength = data.length-minusLength;
          // let wordLength = data.length;
          if (wordLength < this.minTextLength) {
            wordLength = this.minTextLength;
          }
          if (i <= sheet.frozenRow) {
            //处理文本换行
            if (data.indexOf('\n') >= 0) {
              let array = data.split('\n');
              let maxLength = array[0].length;
              for (let item of array) {
                if (item.length > maxLength) {
                  maxLength = item.length;
                }
              }
              wordLength = maxLength;
            }
          }
          wordSum += wordLength;
          if (wordLength > maxLength) {
            maxLength = wordLength;
          }
        }
      }
      if (count <= 0) {
        return 14;
      }
      let avgLength = wordSum / count;
      // if (avgLength < this.minTextLength) {
      //   avgLength = this.minTextLength;
      // }
      let result = avgLength;
      if (avgLength * 4 > maxLength) {
        result = maxLength;
      }
      if(this.maxTextLength>0&&result>this.maxTextLength) {
        result = this.maxTextLength;
      }
      return (result + 2) * 14;
    },

    excelMergeMethod: function ({row, column, rowIndex, columnIndex}, sheet, rowOffset) {
      let sheetName = sheet.name;
      let isVirtualView = this.virtualModeMap[sheetName];
      if(isVirtualView&&row.virtualRowNum) {
        //虚拟视图下dom复用导致rowIndex不准确
        rowIndex = row.virtualRowNum;
      }
      if (!this.excelData.mergeRangeMap) {
        return;
      }
      let excelMergeRowIndex = rowIndex;
      if(rowOffset&&rowOffset>0) {
        //存在锁定表头时主体数据偏移定位
        excelMergeRowIndex=rowIndex+rowOffset;
      } else {
        rowOffset = 0;
      }
      let mergeData = this.excelData.mergeRangeMap[sheetName + "_" + excelMergeRowIndex + "_" + columnIndex];
      if (mergeData) {

        if(isVirtualView&&this.virtualDataRangeMap[sheetName]
            &&this.virtualDataRangeMap[sheetName].start==rowIndex
            &&mergeData.rowspan == 0) {
          //如果是虚拟视图（行虚拟），若当前展示所有行有行合并且行合并开始行不在虚拟视图范围内，需要调整虚拟视图第一条为行合并开始
          let endIndex = rowIndex+1;
          for(;endIndex<this.virtualDataRangeMap[sheetName].end;endIndex++) {
            let tmpMergeData = this.excelData.mergeRangeMap[sheetName + "_" + (endIndex+rowOffset) + "_" + columnIndex];
            if(!tmpMergeData||tmpMergeData.rowspan>0) {
              break;
            }
          }

          //虚拟视图下需要将合并单元格数据转换到新的虚拟合并单元格
          let startIndex = rowIndex-1;
          for(;startIndex>=0;startIndex--) {
            let tmpMergeData = this.excelData.mergeRangeMap[sheetName + "_" + (startIndex+rowOffset) + "_" + columnIndex];
            if(tmpMergeData&&tmpMergeData.rowspan>0) {
              let value = sheet.bodyDataList[startIndex][sheet.colIdList[columnIndex]];
              if(value) {
                sheet.bodyDataList[rowIndex][sheet.colIdList[columnIndex]] = value;
              }
              break;
            }
          }

          // console.log('row:'+rowIndex+'col:'+columnIndex+',rowspan:'+(endIndex-rowIndex)+',colspan:'+mergeData.colspan)
          // console.log(row)
          // console.log(sheet)
          return {
            rowspan: endIndex-rowIndex,
            colspan: mergeData.colspan,
            // 'text-align': align
          };

        } else if(rowIndex == 0&&mergeData.rowspan == 0){
          //解决行合并跨锁定表头问题
          let endIndex = rowIndex+1;
          for(;endIndex<sheet.bodyDataList.length;endIndex++) {
            let tmpMergeData = this.excelData.mergeRangeMap[sheetName + "_" + (endIndex+rowOffset) + "_" + columnIndex];
            if(!tmpMergeData||tmpMergeData.rowspan>0) {
              break;
            }
          }
          return {
            rowspan: endIndex-rowIndex,
            colspan: mergeData.colspan,
            // 'text-align': align
          };
        }
        // console.log('row:'+rowIndex+'col:'+columnIndex+',rowspan:'+mergeData.rowspan+',colspan:'+mergeData.colspan)
        // console.log(row)

        return {
          rowspan: mergeData.rowspan,
          colspan: mergeData.colspan,
          // 'text-align': align
        };
      }

    },
    getCommonCellStyle:function ({row, column, rowIndex, columnIndex}, sheet){
      let result = {};
      if(this.borderColor) {
        result['border-color'] = this.borderColor;
      }
      //设置背景色
      if(this.backgroundColor) {
        result['background-color']=this.backgroundColor;
      }
      if(this.selectedRowMap[sheet.name]==row.rowNum&&this.rowSelectedColor) {
        result['background-color'] = this.rowSelectedColor;
      }
      let canEdit = false;
      if(this.cellEditable) {
        canEdit = this.cellEditable(row, column,sheet);
      }
      if (canEdit&&this.cellEditableColor) {
        result['background-color'] = this.cellEditableColor;
      } else if(row.changed&&this.rowEditedColor&&this.selectedRowMap[sheet.name]!=row.rowNum) {
        //当前行已被编辑，且未被选中，展示行编辑后颜色
        result['background-color'] = this.rowEditedColor;
      }
      return result;
    },
    headerExcelCellStyle:function ({row, column, rowIndex, columnIndex}, sheet,hook){
      let sheetName = sheet.name;
      let mergeData = this.excelData.mergeRangeMap[sheetName + "_" + rowIndex + "_" + columnIndex];
      let result = this.getCommonCellStyle({row, column, rowIndex, columnIndex}, sheet);

      if (mergeData) {
        let align = 'center';
        if (mergeData.align) {
          align = mergeData.align;
        }
        if (hook) {
          let tmp = hook({row, column, rowIndex, columnIndex}, sheet);
          if(tmp) {
            result = Object.assign(result,tmp);
          }
        }
        result['text-align'] = align;
        return result;
      }

      let cellIndex = this.getCellIndex(sheet, row, column);
      if (cellIndex == this.editCellIndex) {
        return {
          'background-color': this.cellEditingColor
        }
      }
      if (hook) {
        let tmp = hook({row, column, rowIndex, columnIndex}, sheet);
        if(tmp) {
          result = Object.assign(result,tmp);
        }
      }
      return result;
    },
    bodyExcelCellStyle: function ({row, column, rowIndex, columnIndex}, sheet,hook) {
      let sheetName = sheet.name;
      if(this.virtualModeMap[sheetName]&&row.virtualRowNum) {
        //虚拟视图下dom复用导致rowIndex不准确
        rowIndex = row.virtualRowNum;
      }
      let mergeRowIndex = sheet.frozenRow+rowIndex;
      let mergeData = this.excelData.mergeRangeMap[sheetName + "_" + mergeRowIndex + "_" + columnIndex];
      let result = this.getCommonCellStyle({row, column, rowIndex, columnIndex}, sheet);

      if (mergeData) {
        let align = 'center';
        if (mergeData.align) {
          align = mergeData.align;
        }
        if (hook) {
          let tmp = hook({row, column, rowIndex, columnIndex}, sheet);
          if(tmp) {
            result = Object.assign(result,tmp);
          }
        }
        result['text-align'] = align;
        return result;
      }

      let cellIndex = this.getCellIndex(sheet, row, column);
      if (cellIndex == this.editCellIndex) {
        return {
          // border:'1px solid #5584ff',
          // 'background-color':'rgb(240, 249, 235)'
          'background-color': this.cellEditingColor
        }
      }

      if (hook) {
        let tmp = hook({row, column, rowIndex, columnIndex}, sheet);
        if(tmp) {
          result = Object.assign(result,tmp);
        }
      }
      return result;
    },


    showCellDetail: function (sheet, row, column) {
      this.detailCellIndex = this.getCellIndex(sheet, row, column);
    },
    rowClassName({row, rowIndex}) {
      if(row.virtualRowNum) {
        //虚拟视图下dom复用导致rowIndex不准确
        rowIndex = row.virtualRowNum;
      }
      if (row.changed) {
        return 'changed';
      }
      return "";
    },
    getActiveTab() {
      return this.resultTabName;
    },
    editCell(sheet, row, column) {
      this.editCellIndex = this.getCellIndex(sheet, row, column);
      this.$nextTick(() => {
        let input = this.$refs['cellInput_' + this.editCellIndex];
        if (Array.isArray(input) && input.length > 0) {
          input[0].focus();
        } else if (input && input.focus) {
          input.focus();
        }
      })
    },
    cancelEdit(row,column) {
      // console.log(e)
      this.editCellIndex = '';
      this.$emit("cell-blur",row,column);
    },
    getCellIndex(sheet, row, column) {
      return sheet.name + '_' + row.virtualRowNum + '_' + column.property;
    },

    updateVirtualDataRange({start,end}) {
      //记录当前表格虚拟展示数据范围
      this.virtualDataRangeMap[this.resultTabName] = {start:start,end:end};
    },
    changeInput(row,column) {
      if(!row) {
        return;
      }
      row.changed=true;
      this.$emit("cell-input",row,column);
    },

    //判断右侧固定列是否展示
    rightFixColumnShowable(fixCol,sheet) {
      if(!fixCol.isShow) {
        return true;
      }
      return fixCol.isShow(sheet);
    },

    //监听鼠标按下事件，列宽调整开始
    handleMouseDown(event,sourceRef,targetRef) {
      // if (column.children && column.children.length > 0) return;
      /* istanbul ignore if */
      if(!this.draggingColumn) {
        return;
      }
      let column = this.draggingColumn;
      if (this.draggingColumn) {
        this.dragging = true;

        const table = this.$refs[sourceRef][0];
        let targetRefObj = this.$refs[targetRef];
        const targetTable = targetRefObj?targetRefObj[0]:null;
        let targetColumn = null;
        if(targetTable) {
          targetTable.resizeProxyVisible = true;
          for (let item of targetTable.columns) {
            if (item.property == column.property) {
              targetColumn = item;
              break;
            }
          }
        }
        table.resizeProxyVisible = true;
        const tableEl = table.$el;
        const tableLeft = tableEl.getBoundingClientRect().left;
        //排除合并单元格情况
        const columnEls = this.$el.querySelectorAll(`td.${column.id}`);
        let tmpColumnEl = null;
        for(let item of columnEls) {
          if(item.getAttribute('colspan') == 1){
              tmpColumnEl = item;
              break;
          }
        }
        if(!tmpColumnEl) {
          this.draggingColumn = null;
          return;
        }
        const columnEl = tmpColumnEl;
        const columnRect = columnEl.getBoundingClientRect();
        const minLeft = columnRect.left - tableLeft + 30;

        addClass(columnEl, 'noclick');

        this.dragState = {
          startMouseLeft: event.clientX,
          startLeft: columnRect.right - tableLeft,
          startColumnLeft: columnRect.left - tableLeft,
          tableLeft
        };

        const resizeProxy = table.$refs.resizeProxy;
        resizeProxy.style.left = this.dragState.startLeft + 'px';

        const targetResizeProxy = targetTable?targetTable.$refs.resizeProxy:null;
        if(targetResizeProxy) {
          targetResizeProxy.style.left = this.dragState.startLeft + 'px';
        }

        document.onselectstart = function() { return false; };
        document.ondragstart = function() { return false; };

        const handleMouseMove = (event) => {
          const deltaLeft = event.clientX - this.dragState.startMouseLeft;
          const proxyLeft = this.dragState.startLeft + deltaLeft;

          resizeProxy.style.left = Math.max(minLeft, proxyLeft) + 'px';
          if(targetResizeProxy) {
            targetResizeProxy.style.left = Math.max(minLeft, proxyLeft) + 'px';
          }
        };

        const handleMouseUp = () => {
          if (this.dragging) {
            const {
              startColumnLeft,
              startLeft
            } = this.dragState;
            const finalLeft = parseInt(resizeProxy.style.left, 10);
            const columnWidth = finalLeft - startColumnLeft;
            column.width = column.realWidth = columnWidth;
            table.$emit('header-dragend', column.width, startLeft - startColumnLeft, column, event);

            table.store.scheduleLayout();

            document.body.style.cursor = '';
            this.dragging = false;
            this.draggingColumn = null;
            this.dragState = {};

            table.resizeProxyVisible = false;
            if(targetColumn) {
              targetColumn.width = targetColumn.realWidth = columnWidth;
              targetTable.$emit('header-dragend', targetColumn.width, startLeft - startColumnLeft, targetColumn, event);
              targetTable.store.scheduleLayout();
              targetTable.resizeProxyVisible = false;
            }
          }

          document.removeEventListener('mousemove', handleMouseMove);
          document.removeEventListener('mouseup', handleMouseUp);
          document.onselectstart = null;
          document.ondragstart = null;

          setTimeout(function() {
            removeClass(columnEl, 'noclick');
          }, 0);
        };

        document.addEventListener('mousemove', handleMouseMove);
        document.addEventListener('mouseup', handleMouseUp);
      }
    },
    //处理单元格移入，记录列宽调整列信息
    handleMouseEnter(row, column, cell, event) {
      if(this.dragging) {
        return;
      }
      let colspan = cell.getAttribute('colspan');
      if(colspan!=1) {
        this.draggingColumn = null;
        return;
      }
      let target = event.target;
      while (target && target.tagName !== 'TD') {
        target = target.parentNode;
      }

      if (!column || !column.resizable) {
        this.draggingColumn = null;
        return;
      }

      if (!this.dragging) {
        let rect = target.getBoundingClientRect();
        const bodyStyle = document.body.style;
        if (rect.width > 12 && rect.right - event.pageX < 18) {
          bodyStyle.cursor = 'col-resize';
          if (hasClass(target, 'is-sortable')) {
            target.style.cursor = 'col-resize';
          }
          this.draggingColumn = column;
        } else if (!this.dragging) {
          bodyStyle.cursor = '';
          if (hasClass(target, 'is-sortable')) {
            target.style.cursor = 'pointer';
          }
          this.draggingColumn = null;
        }
      }
    },
    //处理鼠标移动，用于列宽调整鼠标样式切换
    handleMouseMove(event) {
      if(this.dragging) {
        return;
      }
      if(!this.draggingColumn) {
        return;
      }
      let target = event.target;
      while (target && target.tagName !== 'TD') {
        target = target.parentNode;
      }

      if(!target) {
        return;
      }
        let rect = target.getBoundingClientRect();
        const bodyStyle = document.body.style;
        if (rect.width > 12 && rect.right - event.pageX < 18) {
          bodyStyle.cursor = 'col-resize';
          if (hasClass(target, 'is-sortable')) {
            target.style.cursor = 'col-resize';
          }
        } else if (!this.dragging) {
          bodyStyle.cursor = '';
          if (hasClass(target, 'is-sortable')) {
            target.style.cursor = 'pointer';
          }
          this.draggingColumn = null;
        }
    },

    handleMouseOut() {
      document.body.style.cursor = '';
    },
  }

}
</script>

